
#ifndef EVENT_H_
#define EVENT_H_

#include "RealTimeType.h"

namespace p2 {

class Event: public RealTimeType
{
protected:
	virtual ~Event();
};

class Delegate
{
public:
	virtual ~Delegate();
	inline bool dispatch(Event* event);
private:
	virtual bool execute(Event* event) = 0;
};

inline bool Delegate::dispatch(Event* event)
{
	return execute(event);
}

template<class T, class EventT>
class InstanceDelegate: public Delegate
{
	typedef bool (T::* MemFunc)(EventT* );
public:
	inline InstanceDelegate(T* inst, MemFunc func);
	virtual ~InstanceDelegate() { }
private:
	inline bool execute(Event* event);
private:
	T* _inst;
	MemFunc _func;
};

template<class T, class EventT>
inline InstanceDelegate<T, EventT>::InstanceDelegate(T* inst, MemFunc func)
	: _inst(inst), _func(func)
{
}

template<class T, class EventT>
inline bool InstanceDelegate<T, EventT>::execute(Event* event)
{
	return (_inst->*_func)(static_cast<EventT*>(event));
}

class EventDispatcher
{
	typedef boost::unordered_map<rttid, Delegate* > DelegateHash;
public:
	inline EventDispatcher();
	virtual ~EventDispatcher();

	template<class T, class EventT>
	inline bool registerMethod(T* inst, bool (T::* func)(EventT* ));
	inline bool dispatch(Event* event);

private:
	DelegateHash _delegates;
};

inline EventDispatcher::EventDispatcher()
	: _delegates()
{
}

template<class T, class EventT>
inline bool EventDispatcher::registerMethod(T* inst, bool (T::* func)(EventT* ))
{
	_delegates[EventT::classId()] = new InstanceDelegate<T, EventT>(inst, func);
	return true;
}

inline bool EventDispatcher::dispatch(Event* event)
{
	DelegateHash::iterator iter = _delegates.find(event->Id());
	if (iter != _delegates.end()) {
		return iter->second->dispatch(event);
	}
	return false;
}

}

#endif	//EVENT_H_
